import os
import shutil
import sys
from flask import Flask
# import pymysql
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.orm import Session
from app.config import VSConfig
from app.libs import utils
from app.models.chapter import Chapter
from app.models.course import Course
from app.models.user import User
from app.models.video import Video
from app.libs.utils.mock import Mock
from vsearcher import VSearcher
# pymysql.install_as_MySQLdb()  # 规避数据库连接问题


def load_argv():
    """ 加载sys.argv的参数(即cmd传入的参数)到配置参数 """
    def get_value(arg):
        return arg.split('=')[1]
    for i, args in enumerate(sys.argv):
        if args.startswith('step'):
            step = int(get_value(sys.argv[i]))
            VSearcher.config.args.step = step
        if args.startswith('speed'):
            speed_x = int(get_value(sys.argv[i]))
            VSearcher.config.args.speed_x = speed_x


print('+++++++++++++项目路径++++++++++++++++')
print(utils.getProjectRootPath(__file__, __name__, relative=True))


def create_app():
    # app = Flask(__name__, static_folder='', static_url_path='', static_host='')
    # @NOTE 静态文件可以分离 并且设置域名，路径 蓝图也是同样可以的
    app = Flask(__name__)
    from .config import secure, setting
    # @MODIFYED 如此导入， 将无法被 pyinstaller打包工具识别，将导致出错
    # app.config.from_pyfile('config/secure.py')
    # app.config.from_pyfile('config/setting.py')
    app.config.from_object(secure)
    app.config.from_object(setting)

    from .models import db
    db.init_app(app=app)
    db.app = app

    # 初配置vsearcher库
    # @RISK 全部都是静态的方法，遇到多线程时，最底层不会冲突，因为加了锁，但是配置步长这些的设置使用的是全局性比较强的配置文件
    VSearcher.config.performance.th_video_multiple_nums = VSConfig.th_video_multiple_nums
    VSearcher.config.performance.use_gpu = VSConfig.use_gpu
    VSearcher.config.performance.th_mul_thread_on_frame_counts = VSConfig.th_mul_thread_on_frame_counts
    VSearcher.init(
        domain_url=VSConfig.domain_url,  # 外部接口返回域名
        project_root_dir=utils.getProjectRootPath(
            __file__, __name__, relative=True),
        static_folder=VSConfig.static_folder,
        output_dir=VSConfig.output_dir,
        ocr_model_dir=VSConfig.ocr_model_dir,
        step=VSConfig.step,
        speed_x=VSConfig.speed_x
    )
    load_argv()  # 加载sys.argv中的参数
    print(
        f'全局默认 step: {VSearcher.config.args.step} | speed: {VSearcher.config.args.speed_x}')

    # 模拟生成数据（自动创建管理员用户）  并 重置所有数据
    mock_data(db, reset=False)
    # 初始化
    if not os.path.exists(app.config['VIDEO_TEMP_DIR']):
        os.makedirs(app.config['VIDEO_TEMP_DIR'])
    else:
        shutil.rmtree(app.config['VIDEO_TEMP_DIR'], ignore_errors=True)
        os.makedirs(app.config['VIDEO_TEMP_DIR'])
    # 初始化vs库

    register_blueprint(app=app)
    return app


def register_blueprint(app: Flask):
    from .api import bp_api
    app.register_blueprint(bp_api)


def mock_data(db: SQLAlchemy, reset):

    # 添加超级管理员
    def add_admin(session: Session):
        print("================================================================")
        print("管理员账户生成成功!")
        print("================================================================")
        root_user = User(id=1, account='root', password='root',
                         scope=99, nickname='超级管理员')
        session.add(root_user)

    # 重置表的设置

    def add(mock: Mock, session: Session):

        users = mock.create(User, 3, {
            'account': 'user',
            'password': '123456'
        })

        videos = mock.create(Video, 3, {
            'name': 'video',
            'user_id': 1,
            'chapter_id': 1,
            'o_path': 'video_object_path'
        })

        chapters = mock.create(Chapter, 3, dict(
            name='chapter',
            user_id=1,
            course_id=1,
            o_path='chapter_object_path'
        ))

        courses = mock.create(Course, 3, dict(
            name='course',
            user_id=1,
            o_path='course_object_path'
        ))

        session.add_all(users)
        session.add_all(courses)
        session.add_all(chapters)
        session.commit()
        session.add_all(videos)
        session.commit()

    def update(mock: Mock, session: Session):
        form_data = {
            'account': 'userx',
            'password': '123x',
            # 'nickname1': 'fake_nick'
        }  # 还是用 set_attr比较好
        un = User(**form_data)
        u = session.query(User).filter_by(id=2).first()
        users = User.query.all()
        u3 = User.query.filter(User.id == 3).first()
        u1 = User.query.get(1)
        # session.query(User).filter_by(id=1).update()
        User.query.get(1).nickname = '老用户'
        # User.query.filter(User).update({'password': User.password})
        ut = session.query(User.account, User.password)
        pass
    if reset:
        with Mock(db, reset=reset) as mock:
            add_admin(mock.get_session())
    else:
        has_table = db.engine.dialect.has_table(
            db.engine.connect(), "user")
        if not has_table:
            with Mock(db, reset=True) as mock:
                add_admin(mock.get_session())

        # add(mock, session)
        # update(mock, session)
        # pass
